package com.example.gm.config;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.oauth2.jwt.JwtDecoder;
import org.springframework.security.oauth2.jwt.JwtEncoder;
import org.springframework.security.oauth2.jwt.NimbusJwtDecoder;
import org.springframework.security.oauth2.jwt.NimbusJwtEncoder;
import org.springframework.security.web.SecurityFilterChain;

import com.nimbusds.jose.jwk.source.ImmutableSecret;
import com.nimbusds.jose.jwk.source.JWKSource;
import com.nimbusds.jose.proc.SecurityContext;

@Configuration
public class GmSecurityConfig {
	
	@Value("${gm.security.secret}")
	String secret; // JWT秘钥
	
	@Bean
	public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {		
		http
			.authorizeHttpRequests(authorize-> {
				authorize
					// 放行OPTIONS请求
			        .requestMatchers(HttpMethod.OPTIONS, "/**").permitAll()
					// api 开头的都需要认证
					.requestMatchers("/api/**").authenticated()
					// 其他所有请求都放行
					.anyRequest().permitAll();
			})
			.csrf(csrf -> csrf.disable())
			.oauth2ResourceServer((oauth2) -> oauth2.jwt(Customizer.withDefaults()))
			.sessionManagement((session) -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS));			
		return http.build();
	}

	@Bean
	JwtDecoder jwtDecoder() {
		// RSA
		//return NimbusJwtDecoder.withPublicKey(this.key).build();
		// 改用对称解密 HmacSHA256
		SecretKey originalKey = new SecretKeySpec(secret.getBytes(), "HmacSHA256");
	    NimbusJwtDecoder jwtDecoder = NimbusJwtDecoder.withSecretKey(originalKey).build();
	    return jwtDecoder;
	}

	@Bean
	JwtEncoder jwtEncoder() {
		// RSA
		//JWK jwk = new RSAKey.Builder(this.key).privateKey(this.priv).build();
		//JWKSource<SecurityContext> jwks = new ImmutableJWKSet<>(new JWKSet(jwk));
		//return new NimbusJwtEncoder(jwks);
		// 改用对称加密 HmacSHA256
		SecretKey key = new SecretKeySpec(secret.getBytes(), "HmacSHA256");
	    JWKSource<SecurityContext> immutableSecret = new ImmutableSecret<SecurityContext>(key);
	    return new NimbusJwtEncoder(immutableSecret);
	}
}
